﻿using CommunityToolkit.Mvvm.Input;
using Mapster;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UpperComputer.Application;
using UpperComputer.WPF.Entry.Common;
using UpperComputer.WPF.Entry.Models;
using UpperComputer.WPF.Entry.Views;
using YFurion.Application;

namespace UpperComputer.WPF.Entry.ViewModels
{
    public class MainViewModel : BaseViewModel
    {
        private readonly IBaseUserService _userService;
        private readonly IBaseMenuService _menuService;
        private readonly IBaseRolePermissionService _rolePermissionService;

        /// <summary>
        /// 仪表盘命令
        /// </summary>
        public IRelayCommand DashboardCommand { get; }

        /// <summary>
        /// 密码修改对话框打开命令
        /// </summary>
        public IAsyncRelayCommand PasswordChangeCommand { get; }

        /// <summary>
        /// 语言选择命令
        /// </summary>
        public IAsyncRelayCommand LanguageSelectCommand { get; }

        /// <summary>
        /// 菜单展开命令
        /// </summary>
        public IRelayCommand<MenuModel> MenuExpandCommand { get; }

        /// <summary>
        /// 菜单选择命令
        /// </summary>
        public IRelayCommand<BaseMenuResultDto> MenuSelectCommand { get; }

        public ObservableCollection<MenuModel> Menus { get; } = new ObservableCollection<MenuModel>();

        private bool _isDashboard = true;
        /// <summary>
        /// 是否是仪表盘
        /// </summary>
        public bool IsDashboard
        {
            get => _isDashboard;
            set => SetProperty(ref _isDashboard, value);
        }

        private string _currentModule;
        /// <summary>
        /// 当前模块
        /// </summary>
        public string CurrentModule
        {
            get => _currentModule;
            set => SetProperty(ref _currentModule, value);
        }

        private string _currentPage;
        /// <summary>
        /// 当前页面
        /// </summary>
        public string CurrentPage
        {
            get => _currentPage;
            set => SetProperty(ref _currentPage, value);
        }

        /// <summary>
        /// 登陆用户信息
        /// </summary>
        private BaseUserResultDto _loginUser;
        public BaseUserResultDto LoginUser
        {
            get => _loginUser;
            set => SetProperty(ref _loginUser, value);
        }

        /// <summary>
        /// 中文月份数组
        /// </summary>
        private readonly string[] _chinesWeeks = new string[] { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };

        /// <summary>
        /// 英文星期数组
        /// </summary>
        private readonly string[] _englishWeeks = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

        /// <summary>
        /// 计时器
        /// </summary>
        private readonly Timer _timer;

        private string _dateText;
        /// <summary>
        /// 日期文本
        /// </summary>
        public string DateText
        {
            get => _dateText;
            set => SetProperty(ref _dateText, value);
        }

        private string _timeText;
        /// <summary>
        /// 时间文本
        /// </summary>
        public string TimeText
        {
            get => _timeText;
            set => SetProperty(ref _timeText, value);
        }

        private string _weekText;
        /// <summary>
        /// 日期文本
        /// </summary>
        public string WeekText
        {
            get => _weekText;
            set => SetProperty(ref _weekText, value);
        }

        private Dictionary<long, string> _waringPairs = new Dictionary<long, string>
        {
             {0,"暂无警告" }
        };

        /// <summary>
        /// 警告字典
        /// </summary>
        public Dictionary<long, string> WaringPairs
        {
            get => _waringPairs;
            set => SetProperty(ref _waringPairs, value);
        }

        private bool _communicationStatus;
        /// <summary>
        /// 通信状态
        /// </summary>
        public bool CommunicationStatus
        {
            get => _communicationStatus;
            set => SetProperty(ref _communicationStatus, value);
        }

        public MainViewModel(IBaseUserService userService,
            IBaseMenuService menuService,
            IBaseRolePermissionService rolePermissionService)
        {
            DashboardCommand_Execute();
            _userService = userService;
            _menuService = menuService;
            _rolePermissionService = rolePermissionService;
            DashboardCommand = new RelayCommand(DashboardCommand_Execute);
            PasswordChangeCommand = new AsyncRelayCommand(PasswordChangeCommand_Execute);
            LanguageSelectCommand = new AsyncRelayCommand(LanguageSelectCommand_Execute);
            MenuExpandCommand = new RelayCommand<MenuModel>(MenuExpandCommand_Execute);
            MenuSelectCommand = new RelayCommand<BaseMenuResultDto>(MenuSelectCommand_Execute);

            _timer = new Timer((state) =>
            {
                SetDateTimeText();
            }, null, 0, Constant.TIMER_INTERVAL);
        }

        /// <summary>
        /// 异步加载
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected override async Task LoadAsync(object parameter, CancellationToken cancellationToken)
        {
            LoginUser = await _userService.GetCacheById(YSession.SubjectId, cancellationToken);
            BaseMenuResultRequestDto menuInput = new BaseMenuResultRequestDto()
            {
                IsActive = true,
                CanSearchMenuButtons = true,
            };
            List<BaseMenuResultDto> menus = await _menuService.GetMenus(menuInput, cancellationToken);
            if (YSession.Account != Constant.ADMIN)
            {
                string[] roleCodes = await _userService.GetRoleCodesCache(LoginUser, cancellationToken);
                BaseRolePermissionResultRequestDto rolePermissionResultRequestDto = new BaseRolePermissionResultRequestDto
                {
                    RoleCodes = roleCodes
                };
                PagedResultDto<BaseRolePermissionDto> rolePermissionPagedResultDto =
                await _rolePermissionService.GetAll(rolePermissionResultRequestDto, cancellationToken);
                GetPermissions(menus, rolePermissionPagedResultDto.Items);
            }
            foreach (BaseMenuResultDto menu in menus)
            {
                Menus.Add(menu.Adapt<MenuModel>());
            }
        }

        /// <summary>
        /// 获取权限
        /// </summary>
        /// <param name="menuDtos"></param>
        /// <param name="rolePermissionDtos"></param>
        private void GetPermissions(ICollection<BaseMenuResultDto> menuDtos, IReadOnlyList<BaseRolePermissionDto> rolePermissionDtos)
        {
            for (int i = 0; i < menuDtos.Count; i++)
            {
                BaseMenuResultDto menuDto = menuDtos.ElementAt(i);
                if (menuDto.Childrens?.Count > 0)
                {
                    GetPermissions(menuDto.Childrens, rolePermissionDtos);
                }

                bool hasMenu = false;
                foreach (BaseRolePermissionDto item1 in rolePermissionDtos)
                {
                    if (item1.PermissionCode == menuDto.Code)
                    {
                        hasMenu = true;
                        if (menuDto.BaseMenuButton.Count > 0)
                        {
                            for (int j = 0; j < menuDto.BaseMenuButton.Count; ++j)
                            {
                                BaseMenuButtonResultDto menuButtonDto = menuDto.BaseMenuButton.ElementAt(j);
                                bool hasMenuButton = false;
                                foreach (BaseRolePermissionDto item2 in rolePermissionDtos)
                                {
                                    if (item2.PermissionCode == menuButtonDto.MenuCode + menuButtonDto.Code)
                                    {
                                        hasMenuButton = true;
                                        break;
                                    }
                                }

                                if (!hasMenuButton)
                                {
                                    menuDto.BaseMenuButton.Remove(menuButtonDto);
                                    --j;
                                }
                            }
                        }
                        break;
                    }
                }

                if (!hasMenu)
                {
                    menuDtos.Remove(menuDto);
                    --i;
                }
            }
        }

        /// <summary>
        /// 仪表盘命令执行方法
        /// </summary>
        private void DashboardCommand_Execute()
        {
            foreach (MenuModel item in Menus)
            {
                item.SelectedMenu = null;
            }
            IsDashboard = false;
            CurrentModule = Lang["仪表盘"];
            CurrentPage = "DashboardPage.xaml";
        }

        /// <summary>
        /// 修改密码命令执行方法
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task PasswordChangeCommand_Execute(CancellationToken cancellationToken)
        {
            UserPasswordControl userPasswordControl = Furion.App.GetService<UserPasswordControl>();
            await ShowRootDialog(userPasswordControl);
        }

        /// <summary>
        /// 语言选择命令执行方法
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task LanguageSelectCommand_Execute(CancellationToken cancellationToken)
        {
            SetLang();
            //如果是仪表盘更新当前模块名
            if (CurrentPage.Equals("DashboardPage.xaml"))
            {
                CurrentModule = Lang["仪表盘"];
            }
            //更新Page页面语言
            string target = CurrentPage;
            CurrentPage = string.Empty;
            await Task.Delay(15, cancellationToken);
            CurrentPage = target;
        }

        /// <summary>
        /// 菜单展开命令执行方法
        /// </summary>
        /// <param name="menu"></param>
        private void MenuExpandCommand_Execute(MenuModel menu)
        {
            if (menu == null)
            {
                return;
            }
            foreach (MenuModel item in Menus)
            {
                if (!item.Equals(menu))
                {
                    item.IsExpanded = false;
                }
            }
        }

        /// <summary>
        /// 菜单选择命令执行方法
        /// </summary>
        /// <param name="menu"></param>
        private void MenuSelectCommand_Execute(BaseMenuResultDto menu)
        {
            if (menu == null)
            {
                return;
            }
            if (menu.DisplayName.Equals(CurrentModule))
            {
                return;
            }
            foreach (MenuModel item in Menus)
            {
                if (item.SelectedMenu != null && !item.SelectedMenu.Equals(menu))
                {
                    item.SelectedMenu = null;
                }
            }
            IsDashboard = true;
            CurrentModule = menu.DisplayName;
            string cacheKey = $"{menu.Code}Page";
            DistributedCache.Set(cacheKey, menu.BaseMenuButton);
            CurrentPage = $"{cacheKey}.xaml";
        }

        /// <summary>
        /// 设置日期时间文本
        /// </summary>
        private void SetDateTimeText()
        {
            DateTimeOffset dateTimeOffset = DateTimeOffset.Now;
            DateText = dateTimeOffset.ToString("yyyy-MM-dd");
            TimeText = dateTimeOffset.ToString("HH:mm");
            int weekIndex = Convert.ToInt32(dateTimeOffset.DayOfWeek);
            WeekText = Culture == Constant.LANG_ZH_CN ? _chinesWeeks[weekIndex] : _englishWeeks[weekIndex];
        }
    }
}
